
package server;


import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Encapsulates Request object.
 * It also composites RequestHeadder object and is responsible for filling info in it.
 * @author Peewhy
 */
public class Request {
    public final String argSeperator = " ";
    public final String argvSeperator = ":";
    
    private static final String ARG_HOST = "HOST";
    private static final String ARG_USERAGENT = "USER-AGENT";
    private static final String ARG_ACCEPTLANGUAGE = "ACCEPT-LANGUAGE";
    private static final String ARG_ACCEPTENCODING = "ACCEPT-ENCODING";
    private static final String ARG_ACCEPTCHARSET = "ACCEPT-CHARSET";
    private static final String ARG_CONNECTION="CONNECTION";
    private static final String ARG_CACHECONTROL="CACHE-CONTROL";
    
    public RequestHeader header;
    private String postData;
    
    // get params
    private Map<String, String> parameters;

    /**
     * Initialiazes requestHeader
     */
    public Request(){
        header = new RequestHeader();
        postData = "";
        parameters = new HashMap<String, String>();
    }
    
    
    // Add one more line of parsed data
    public void addPostDataLine(String line) {
    	postData += line;
    }
    
    // Retrieve all parsed data
    public String getPostData() {
    	return this.postData;
    }
    
	public void parseParams(String params) {					
		String[] pairs = params.split("&");
		if (pairs.length > 0) {
			for (String item : pairs) {
				String[] vals = item.split("=");
				if (vals.length == 2) {
					String arguement = vals[0];
					String value = java.net.URLDecoder.decode(vals[1]);
					parameters.put(arguement, value);
				}
			}
		}
	}	
        
	// Decode parameters from POST
    public void parsePostData() {    	
    	this.parseParams(getPostData());
    }
    
    // Decode parameters from GET
    public void parseGetData() {
    	this.parseParams(header.getUrlParams());
    }
    
    /**
     * Parses first HTTP request header line.
     * Format is as defined: METHOD_URL_HTTPVERSION
     * @param line First header line
     * @throws java.lang.IllegalArgumentException if line is empty or null, or does not fit format
     */
    public void parseFirstLine(String line) throws IllegalArgumentException {
        if (line == null) throw new IllegalArgumentException("First request line empty");
        if (line.equals("")) throw new IllegalArgumentException("First request line empty");
        
        // Format: method_url_version
        String[] args = line.split(argSeperator);
        if (args.length < 3) throw new IllegalArgumentException(); 
        
            header.setMethod(args[0]);            
            header.setUrl(args[1]);
            header.setHttpVersion(args[2]);
        
        //catch (IndexOutOfBoundsException ioobe) {
        //  throw new IllegalArgumentException(ioobe.getLocalizedMessage());  
        //}
    }
    
    // Get GET request param
    public String getParam(String key) {
    	return this.parameters.get(key);
    }
    
    /**
     * Parses some of header line
     * @param line One of header line, to be parsed
     * @return true, if it was parsed, does not throw an Exception
     */
    public boolean parseLine(String line) {
        boolean ok = true;
        if (line == null) return false;
        if (line.equals("")) return false;
        String[] args = line.split(argvSeperator);
        try {
            // Find cannonical (trimed, capitalized) rerpesentation of String
            String argument = args[0];
            argument = argument.toUpperCase();
            argument = argument.trim();
            
            String value = args[1];
            value = value.trim(); // ???
            
            if (argument.equals(ARG_HOST)){
                header.setHost(value); 
            }
            else if (argument.equals(ARG_USERAGENT)){
                header.setUserAgent(value);
            }
            else if (argument.equals(ARG_ACCEPTLANGUAGE)) {
                header.setAcceptLanguage(value);
            }
            else if (argument.equals(ARG_ACCEPTENCODING)){
                header.setAcceptEncoding(value);
            }
            else if (argument.equals(ARG_ACCEPTCHARSET)){
                header.setAcceptCharset(value);
            }
            else if (argument.equals(ARG_CONNECTION)){
                header.setConnection(value);
            }
            else if (argument.equals(ARG_CACHECONTROL)){
                header.setCacheControl(value);
            }
            else {
                ok = false;
            }
        }
        catch (Exception e) { // dont want to throw exception 
            return false;
        }
        return ok;
    }
}
